7장. 스스로 검색하는 AI 만들기
출처: 『RAG 마스터: 랭체인으로 완성하는 LLM 서비스』(브라이스 유·조경아·박수진·김재웅, 프리렉 2025) | 공식: www.langchain.com
코드는 분위기만 —
create_agent·temperature=0·invoke같은 말은 몰라도 됩니다. 표의 '비유'와 '위험'만 봐도 충분해요.
지금까지 RAG는 "질문 들어오면 → 문서 한 번 찾고 → 답한다" 한 줄이었다.
이 장은 그 한 줄을 여러 번 도는 AI로 바꾼다.
AI가 스스로 "지금 뭘 더 찾아야 하지?"를 생각하고, 필요한 만큼 검색을 반복한다.
천천히 읽으면 된다.
0. 이 장의 새 단어 (0장에 없는 것만 3개)
이 셋만 알면 7장이 다 풀린다.
나머지 어려운 말(임베딩·벡터DB·검색기·청크 등)은 전부 0장 용어집에 있다.
에이전트(Agent)
한 문장 뜻 — 목표를 받으면 스스로 "지금 뭘 할지" 정하고 행동하는 AI.
일상비유 — 심부름 시킬 때 일일이 안 일러줘도 되는 똑똑한 비서. "저녁거리 사 와" 한마디면, 알아서 냉장고 보고 → 장 볼 목록 짜고 → 마트 가서 산다.
한 줄 예 —
# "비교해 줘" 한마디 → AI가 알아서 검색 2번 돌리고 정리
# 준비한 흐름에 실제 입력을 넣어 결과를 확인합니다.
agent.invoke({"input": "미국과 일본 정책 비교해 줘"})
ReAct(리액트)
한 문장 뜻 — AI가 생각하고(Reason) → 행동하는(Act) 걸 번갈아 반복하는 방식.
일상비유 — 탐정 수사. 현장 보고(관찰) → 가설 세우고(생각) → 단서 찾으러 가고(행동) → 또 본다. 답이 나올 때까지 이 고리를 돈다.
한 줄 예 —
# 생각 → 행동 → 관찰을 목표 달성까지 반복하는 AI를 만든다
# 답변을 생성할 LLM 클라이언트나 모델 설정을 준비합니다.
agent = create_agent(llm, tools, system_prompt=prompt)
생각의 사슬(CoT, Chain of Thought)
한 문장 뜻 — 답을 바로 적지 말고 풀이 과정을 먼저 쓰게 시키면, AI가 더 정확해지는 요령.
일상비유 — 수학 시험에서 암산으로 답만 쓰면 틀리는데, 식을 한 줄씩 쓰면 맞히는 것. 과정을 적으면 실수가 준다.
한 줄 예 —
# "바로 답 말고 단계별로 풀어 줘" 라고 시키는 것
# 모델에게 어떤 역할과 입력을 줄지 프롬프트 틀을 만듭니다.
prompt = "단계별로 생각한 뒤 답하세요."
이 장에서 딱 4가지만 (TL;DR)
- ReAct = 생각→행동→관찰을 반복. AI가 탐정처럼 단서를 모아 가며 답에 다가간다.
- CoT(생각의 사슬) = 풀이 과정 먼저 쓰기. ReAct는 매 행동 전에 "생각"을 끼워 이걸 강제한다.
- 에이전트 RAG = 검색을 여러 번 도는 RAG. 일반 RAG는 한 번만 찾지만, 에이전트는 필요한 만큼 반복한다.
- 도구 설명(description)을 잘 써야 AI가 안 헷갈린다. "이 도구는 일본 정보용"이라고 적어 줘야 AI가 골라 쓴다.
학습 목표
- ReAct의 생각→행동→관찰 사이클을 설명한다.
- 생각의 사슬(CoT)이 왜 정확도를 높이는지 설명한다.
- 일반 RAG와 에이전트 RAG의 차이를 구분한다.
- 도구 설명(description)이 왜 중요한지 설명한다.
(귀납 도입) 한 번 찾고 끝, 이게 문제였죠?
지금까지 만든 RAG를 떠올려 보자.
질문이 들어오면 문서 한 번 찾고, 그걸 보고 답한다. 끝.
단순한 질문엔 이걸로 충분하다. "환불 규정 알려줘" → 환불 문서 찾기 → 답. 좋다.
그런데 이런 질문이 들어오면 어떨까.
"미국 정책이랑 일본 정책의 공통점과 차이점을 비교해 줘."
이건 한 번 검색으로 안 된다.
미국 정보도 찾아야 하고, 일본 정보도 따로 찾아야 한다. 그리고 둘을 비교까지 해야 한다.
한 번만 찾는 RAG는 여기서 막힌다. 미국만 찾거나, 일본만 찾거나, 어설프게 섞어서 헛소리를 한다.
# 아래 예제는 핵심 흐름만 짧게 보여 줍니다.
# 한 번만 찾는 RAG — 비교 질문엔 반쪽짜리 답
docs = retriever.invoke("미국과 일본 비교") # 한쪽만 걸려 옴
answer = llm.invoke("미국과 일본 비교" + docs) # 비교가 안 됨
사람이라면 어떻게 할까.
"먼저 미국 자료를 보고, 다음에 일본 자료를 보고, 둘을 견줘 봐야겠다."
이렇게 순서를 스스로 짜서 여러 번 찾아본다.
이걸 AI한테 시키는 게 이번 장의 목표다.
AI가 스스로 "지금 미국부터 찾자 → 다음 일본 찾자 → 이제 비교하자"를 생각하며 검색을 반복하게 만든다.
그 방식 이름이 ReAct다.
1. ReAct — 생각하고 행동하기를 반복
ReAct는 프린스턴 대학교와 구글 연구원들이 함께 만든 방식이다.
이름은 Reason(생각) + Act(행동)을 붙인 말이다.
핵심은 이렇다. AI가 답을 바로 내지 않고, 생각과 행동을 번갈아 반복하며 문제를 풀어 간다.
배운 적 없는 상황, 정보가 부족한 상황에서도 스스로 다음 수를 정한다.
1.1 사이클 4단계 — 생각·행동·행동 입력·관찰
ReAct는 네 단계를 한 바퀴로 돈다.
- 생각(Thought): 지금 상황을 보고, 다음에 뭘 할지 머릿속으로 정한다.
- 행동(Action): 어떤 도구를 쓸지 고른다. (예: 미국 검색기)
- 행동 입력(Action Input): 그 도구에 넣을 구체적인 값을 정한다. (예: "미국 ICT 법령")
- 관찰(Observation): 도구가 내놓은 결과를 본다. 이 결과가 다음 생각의 출발점이 된다.
이 한 바퀴를 답이 나올 때까지 계속 반복한다.
일상비유 — 주방에서 파스타 만들기
저자가 든 예시 그대로 따라가 보자.
- 첫 번째 생각: "파스타를 삶아야 한다. 물 양을 모르겠다. 요리책을 봐야겠다."
- 행동: 요리책 펼치기
- 행동 입력: 목차에서 '파스타' 페이지로 이동
- 관찰: "100g당 물 1L가 필요하다"는 걸 알았다.
여기서 관찰한 것(100g당 1L)이 다음 생각으로 이어진다.
- 두 번째 생각: "300g 삶을 거니까 물 3L가 필요하다. 계량컵을 찾아야겠다."
- 행동: 주방 서랍 열기
- 관찰: 계량컵을 찾았다.
이렇게 본 것을 바탕으로 다음 생각을 하고, 또 행동한다.
우리가 매일 하는 일이다. ReAct는 이 자연스러운 흐름을 AI에 그대로 옮긴 것이다.
| 비유 | 코드 | 위험 |
|---|---|---|
| 탐정: 관찰→가설→단서 찾기 | agent.invoke({"input": 질문}) |
생각 단계 빼면 엉뚱한 행동 |
| 파스타: 책 보고→다음 행동 | agent.stream(...) 으로 과정 보기 |
관찰 무시하면 같은 짓 반복 |
한 문장 정의 — ReAct는 AI가 생각→행동→행동 입력→관찰을 목표 달성까지 반복하며 문제를 단계별로 푸는 방식이다.
단순 규칙 — 막히는 질문은 한 번에 풀지 말고, 사이클을 여러 번 돌려라.
1.2 생각의 사슬(CoT) — 왜 풀이 과정을 먼저 쓰게 할까
ReAct는 매 행동 전에 생각 단계를 꼭 넣는다.
왜 굳이 생각을 시킬까? 여기에 생각의 사슬(CoT)이라는 요령이 숨어 있다.
CoT는 "Chain-of-Thought Prompting…"이라는 논문에서 나온 아이디어다.
내용은 간단하다. 답을 바로 적지 말고, 풀이 과정을 먼저 쓰게 하면 AI가 더 정확해진다.
망가지는 장면 — 암산으로 답만 쓰면 틀린다
저자의 예시를 보자. AI에게 예시 문제를 하나 보여 준다.
예시 질문: 테니스공 5개가 있다. 공 3개짜리 캔을 2개 더 샀다. 지금 몇 개?
예시 정답: 11개 ← 풀이 없이 답만 보여 줌
이제 진짜 문제를 묻는다.
질문: 사과 23개가 있었다. 20개를 쓰고 6개를 더 샀다. 지금 몇 개?
AI 답: 27개 ← 오답! (23-20+6=9가 맞다)
왜 틀렸을까?
AI는 보여 준 예시를 흉내 내는 버릇이 있다.
예시에서 "답만 딱" 적었으니, 진짜 문제도 계산 없이 답만 던진 것이다. 그래서 틀렸다.
고치는 장면 — 예시에 풀이를 넣어 준다
이번엔 예시 답에 풀이 과정을 넣어 준다.
예시 질문: 테니스공 5개, 공 3개짜리 캔 2개를 더 샀다. 몇 개?
예시 정답: 처음 5개. 캔 2개는 공 6개. 5+6=11. 답은 11개. ← 과정을 보여 줌
질문: 사과 23개, 20개 쓰고 6개 샀다. 몇 개?
AI 답: 처음 23개. 20개 썼으니 23-20=3개. 6개 더 사서 3+6=9개. 답은 9개. ← 정답!
예시에서 과정을 보여 줬더니, AI도 과정을 따라 쓰고 정답을 맞혔다.
항상 맞는 건 아니다. 하지만 풀이를 거치게 하면 정확도가 오르는 경우가 많다.
ReAct는 바로 이 요령을 쓴다.
매 행동 전에 "생각"을 강제해서, AI가 덜컥 행동하지 않고 한 번 따져 보게 만든다.
| 비유 | 코드 | 위험 |
|---|---|---|
| 식 쓰고 푸는 수학 답안 | prompt = "단계별로 생각 후 답하세요" |
답만 쓰게 하면 자주 틀림 |
| 예시를 따라 하는 버릇 | 예시에 풀이를 넣어 보여 줌 | 예시가 단답형이면 AI도 단답형 |
한 문장 정의 — 생각의 사슬(CoT)은 답 전에 풀이 과정을 먼저 쓰게 해 AI 정확도를 높이는 요령이고, ReAct는 매 행동 전 '생각'으로 이를 구현한다.
단순 규칙 — AI한테 어려운 걸 시킬 땐 "바로 답 말고, 생각부터 적어"라고 시켜라.
2. 에이전트 RAG — 검색을 여러 번 도는 RAG
이제 ReAct를 RAG에 붙인다.
에이전트 RAG = RAG + AI의 스스로 판단하는 힘.
일반 RAG는 정해진 길로 한 번만 간다. 검색 → 생성. 끝.
에이전트 RAG는 어떤 정보가 더 필요한지 스스로 보고, 필요한 검색을 반복한다.
일상비유 — 정해진 메뉴얼 vs 알아서 하는 비서
일반 RAG는 "들어오면 무조건 1번 서랍 열어 보기" 같은 고정 규칙이다.
에이전트 RAG는 "상황 보고 필요한 서랍을 필요한 만큼 열어 보는" 비서다.
이 장 실습에서는 비서에게 서랍 두 개를 준다.
하나는 일본 ICT 정책 자료, 하나는 미국 ICT 정책 자료다.
AI는 질문을 보고 "이건 미국 서랍" "이건 둘 다 봐야겠네"를 스스로 정한다.
| 비유 | 코드 | 위험 |
|---|---|---|
| 고정 메뉴얼(한 번만) | docs = retriever.invoke(질문) |
비교·복합 질문에 반쪽 답 |
| 알아서 하는 비서(반복) | agent.invoke({"input": 질문}) |
도구 설명 부실하면 오선택 |
한 문장 정의 — 에이전트 RAG는 AI가 어떤 검색이 필요한지 스스로 판단해 여러 번 반복하는 RAG다.
2.1 재료 준비 — 두 개의 자료, 두 개의 서랍
실습은 두 개의 PDF로 시작한다. 일본 ICT 정책 보고서, 미국 ICT 정책 보고서.
각각을 따로따로 벡터DB로 만들어 둔다. (벡터DB·임베딩·청크는 0장 용어집 참고)
그러면 "일본 서랍" "미국 서랍" 두 개가 생긴다.
부품마다 역할이 있다. 대부분 0장에서 본 것들이다.
| 부품 | 하는 일 |
|---|---|
PyMuPDFLoader |
PDF에서 글자 뽑아내기 (문서 로더) |
RecursiveCharacterTextSplitter |
긴 글을 조각(청크)으로 자르기 |
OpenAIEmbeddings |
글을 숫자 묶음(벡터)으로 바꾸기 |
Chroma |
숫자 묶음 저장·검색 창고 (벡터DB) |
create_retriever_tool |
검색기를 에이전트 도구로 변환 ← 7장 새 부품 |
create_agent |
ReAct 에이전트 만들기 (실행 루프 내장) ← 7장 새 부품 |
# 두 나라 PDF를 인터넷에서 내려받는다 (분위기만)
# `urls`에 중간 결과를 담아 다음 줄에서 재사용합니다.
urls = ["...ict_japan_2024.pdf", "...ict_usa_2024.pdf"]
# 목록이나 결과 묶음을 하나씩 꺼내 같은 처리를 반복합니다.
for url in urls:
내려받기(url) # 두 자료를 손에 쥔다
미니 시나리오 — 만약 자료가 셋이면? 한국·일본·미국 PDF를 각각 벡터DB로 만들어 서랍 세 개를 두면 된다. 부품은 똑같고 개수만 는다.
2.2 검색기를 '도구'로 바꾸기 — 설명이 생명
여기가 7장의 핵심이다.
검색기(0장 용어)를 그냥 두면 에이전트가 못 쓴다.
검색기를 에이전트가 쓸 수 있는 도구 모양으로 감싸 줘야 한다. 그 함수가 create_retriever_tool이다.
도구에는 두 가지를 적는다.
- name(이름): 도구를 부르는 짧은 이름. (예:
japan_ict) - description(설명): 이 도구를 언제 써야 하는지 적은 안내문.
여기서 description이 진짜 중요하다.
에이전트는 질문을 받으면, 각 도구의 설명을 읽고 "어느 걸 쓸까"를 고른다.
설명이 부실하면? AI가 엉뚱한 도구를 고른다.
망가지는 장면 — 설명이 모호할 때
# 나쁜 예 — 설명이 두루뭉술
# 질문과 가까운 문서 조각을 찾아오는 검색 단계를 실행합니다.
jp_engine = create_retriever_tool(
# 질문과 가까운 문서 조각을 찾아오는 검색 단계를 실행합니다.
retriever=retriever_japan,
# `name`에 중간 결과를 담아 다음 줄에서 재사용합니다.
name="tool1",
description="정보를 제공합니다.", # 무슨 정보? AI가 못 고름
)
"정보를 제공합니다." 이러면 AI는 일본 질문에도 미국 도구를 집을 수 있다.
고치는 장면 — 설명을 구체적으로
# 좋은 예 — 언제 쓸지 콕 집어 적음
# 질문과 가까운 문서 조각을 찾아오는 검색 단계를 실행합니다.
jp_engine = create_retriever_tool(
# 질문과 가까운 문서 조각을 찾아오는 검색 단계를 실행합니다.
retriever=retriever_japan,
# `name`에 중간 결과를 담아 다음 줄에서 재사용합니다.
name="japan_ict",
# `description`에 중간 결과를 담아 다음 줄에서 재사용합니다.
description="일본의 ICT 시장 동향 정보를 제공합니다. "
# 이 줄은 예제 흐름을 이루는 실제 처리 단계입니다.
"일본 ICT 관련 질문은 이 도구를 쓰세요.",
)
# 질문과 가까운 문서 조각을 찾아오는 검색 단계를 실행합니다.
usa_engine = create_retriever_tool(
# 질문과 가까운 문서 조각을 찾아오는 검색 단계를 실행합니다.
retriever=retriever_usa,
# `name`에 중간 결과를 담아 다음 줄에서 재사용합니다.
name="usa_ict",
# `description`에 중간 결과를 담아 다음 줄에서 재사용합니다.
description="미국의 ICT 시장 동향 정보를 제공합니다. "
# 이 줄은 예제 흐름을 이루는 실제 처리 단계입니다.
"미국 ICT 관련 질문은 이 도구를 쓰세요.",
)
tools = [jp_engine, usa_engine] # 두 도구를 묶어 둔다
이제 AI는 일본 질문엔 japan_ict, 미국 질문엔 usa_ict를 고른다.
| 비유 | 코드 | 위험 |
|---|---|---|
| 서랍에 라벨 붙이기 | description="일본 ICT 질문에 쓰세요" |
라벨 모호하면 엉뚱한 서랍 |
| 서랍마다 따로 보관 | persist_directory 다르게 지정 |
같은 칸 쓰면 자료가 섞임 |
핵심 포인트 — 두 자료의 저장 경로(persist_directory)도 반드시 다르게 줘야 한다. 같은 경로를 쓰면 나중 자료가 먼저 자료를 덮어쓰거나 섞인다.
부분 완성 — 빈칸 채우기
뉴스 검색 도구를 하나 더 만든다면? 설명을 어떻게 쓸까.
# 질문과 가까운 문서 조각을 찾아오는 검색 단계를 실행합니다.
news_engine = create_retriever_tool(
# 질문과 가까운 문서 조각을 찾아오는 검색 단계를 실행합니다.
retriever=news_retriever,
# `name`에 중간 결과를 담아 다음 줄에서 재사용합니다.
name="news_search",
description="________", # 빈칸: "최신 뉴스를 제공합니다. ICT 최신 사건 질문에 쓰세요."
)
단순 규칙 — 도구 설명은 "이 도구는 언제 쓰는지"를 콕 집어 적어라.
2.3 에이전트에게 행동 규칙 알려 주기 (프롬프트)
에이전트에게 "이런 식으로 일해"라고 알려 주는 지시문이 필요하다.
이게 프롬프트다. (프롬프트는 0장 용어)
랭체인에 기본 프롬프트(hwchase17/react)가 있지만 영어에 너무 단순하다.
그래서 한글로 더 자세히 적은 커스텀 프롬프트를 쓴다.
프롬프트 안에는 빈칸 네 개가 있고, 실행할 때 값이 채워진다.
| 빈칸 | 채워지는 값 |
|---|---|
{tools} |
도구들의 이름 + 설명 전체 |
{tool_names} |
도구 이름만 (예: [japan_ict, usa_ict]) |
{input} |
사용자가 지금 물어본 질문 |
{agent_scratchpad} |
지금까지의 생각·행동·관찰 기록 더미 |
마지막 {agent_scratchpad}가 특히 중요하다.
일상비유 — 메모장
에이전트는 한 바퀴 돌 때마다 "생각했고, 이 도구 썼고, 이런 결과 봤다"를 메모장에 적는다.
다음 행동을 정할 때 이 메모장을 다시 읽는다. 그래서 이전에 뭘 했는지 기억하고 이어 간다.
메모장이 없으면? AI는 방금 한 일도 잊고 같은 검색을 또 돌린다.
# 커스텀 프롬프트 (분위기만 — 핵심 규칙만 추렸다)
# 모델에게 어떤 역할과 입력을 줄지 프롬프트 틀을 만듭니다.
template = """다음 형식으로 답하세요:
Thought: 무엇을 할지 항상 먼저 생각하세요.
Action: 쓸 도구 하나를 [{tool_names}] 중에 고르세요.
Action Input: 그 도구에 넣을 값을 적으세요.
Observation: 도구 결과를 봅니다.
... (이 과정이 여러 번 반복될 수 있습니다)
Thought: 이제 최종 답을 알겠습니다.
Final Answer: 최종 답변
## 주의사항
- 항상 Action 전에 Thought를 먼저 쓰세요.
- 한 번에 안 풀리면 문제를 나눠서 푸세요.
- 정보가 모였으면 쓸데없이 반복하지 마세요.
- 묻지 않은 건 검색하지 마세요.
Question: {input}
Thought: {agent_scratchpad}"""
이 프롬프트가 매 행동 전 Thought(생각)를 강제한다.
바로 앞 1.2절에서 본 CoT(생각의 사슬)를 이렇게 구현하는 것이다.
마지막에도 "이제 최종 답을 알겠습니다"라는 생각을 한 번 더 거친 뒤에야 답을 내놓는다. 확신이 설 때만 답하게 하는 장치다.
| 비유 | 코드 | 위험 |
|---|---|---|
| 일하는 메모장 | {agent_scratchpad} |
기록 안 보면 같은 검색 반복 |
| "생각 먼저" 규칙 | Thought: 를 Action 앞에 강제 |
규칙 빼면 덜컥 오선택 |
단순 규칙 — 프롬프트에 "정보 모였으면 그만 반복해"를 꼭 넣어라. 안 그러면 AI가 쓸데없이 검색을 돈다.
2.4 에이전트 조립하기
이제 부품을 끼워 에이전트를 완성한다.
# 1) 두뇌 역할 LLM — temperature=0
# 답변을 생성할 LLM 클라이언트나 모델 설정을 준비합니다.
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# 2) 두뇌 + 도구 + 프롬프트 = ReAct 에이전트 (실행 루프까지 내장)
# 랭체인 1.0 표준 부품입니다: from langchain.agents import create_agent
agent = create_agent(llm, tools, system_prompt=prompt)
# 예전 책 코드의 create_react_agent + AgentExecutor 두 단계가
# 이 한 줄로 합쳐졌다 — 별도 '일꾼'(AgentExecutor)이 더는 필요 없다.
여기서 손잡이 두 개에 주목하자.
temperature=0 — 온도를 0으로 (온도는 0장 용어).
에이전트는 튀는 답이 아니라 지시를 정확히 따르기가 목표다.
온도가 높으면 도구를 엉뚱하게 고르거나 형식을 틀린다. 그래서 0으로 또박또박 시킨다.
과정 눈으로 보기 — invoke 대신 agent.stream(...)으로 돌리면 생각·행동·관찰이 단계별로 흘러나온다.
이게 있어야 "AI가 왜 이 도구를 골랐지?"를 따라갈 수 있다. (예전 책의 verbose=True 손잡이를 대신한다.)
참고로 예전 책에 있던 handle_parsing_errors=True(형식 실수 자동 수습)는 이제 필요 없다 — 현행 도구 호출 방식에는 수습이 기본으로 들어 있다.
| 비유 | 코드 | 위험 |
|---|---|---|
| 또박또박 시키기 | temperature=0 |
온도 높으면 도구 오선택 |
| 속마음 켜기 | agent.stream(...) 으로 과정 보기 |
안 보면 왜 틀렸는지 모름 |
단순 규칙 — 에이전트의 온도(temperature)는 항상 0으로 둬라.
2.5 실제로 굴려 보기 — 한 번, 두 번, 네 번
완성한 에이전트에게 질문을 던진다.
worked example — 단순 질문 (도구 1번 호출)
# 준비한 흐름에 실제 입력을 넣어 결과를 확인합니다.
result = executor.invoke({"input": "한국과 미국의 ICT 기관 협력 사례"})
AI의 속마음을 따라가 보자.
생각(1): 이건 미국 ICT 질문이다. usa_ict 도구를 쓰자.
행동: usa_ict
행동 입력: 한국과 미국의 ICT 협력 사례
관찰: [한-미 FTA, 실리콘밸리 MOU 등 검색 결과]
생각(2): 정보를 충분히 얻었다. 이제 답하자.
최종 답변: 한-미 FTA 발효, 경북 MOU, 광주시 지원 등...
한 번 검색하고 끝. 단순 질문이라 사이클을 한 바퀴만 돌았다.
부분 완성 — 비교 질문 (도구 2번 호출)
# 준비한 흐름에 실제 입력을 넣어 결과를 확인합니다.
result = executor.invoke({
# 이 줄은 예제 흐름을 이루는 실제 처리 단계입니다.
"input": "미국과 일본의 ICT 정책 공통점과 차이점을 설명해 줘"
})
이건 미국·일본 둘 다 찾아야 한다. AI가 어떻게 할까?
생각(1): 두 나라를 다 봐야 한다. 먼저 미국부터.
행동: usa_ict 관찰: [미국 정책 결과]
생각(2): 이제 일본도 필요하다.
행동: ________ ← (빈칸: japan_ict)
관찰: [일본 정책 결과]
생각(3): 둘 다 모였다. 비교해서 답하자.
최종 답변: [공통점·차이점 분석]
AI가 스스로 "미국 → 일본 → 비교" 순서를 짜서 두 번 검색했다.
도입부에서 막혔던 비교 질문이, 이제 풀린다.
독립 적용 — 복합 질문 (도구 4번 호출)
# 준비한 흐름에 실제 입력을 넣어 결과를 확인합니다.
result = executor.invoke({
# 이 줄은 예제 흐름을 이루는 실제 처리 단계입니다.
"input": "미국의 ICT 정부 기구, 주요 법령, 기업 진출 사례를 각각 검색하고, "
# 이 줄은 예제 흐름을 이루는 실제 처리 단계입니다.
"그다음 일본의 AI 정책도 알려 줘"
})
이 질문엔 미국 항목이 셋, 일본 항목이 하나 들어 있다.
AI는 스스로 네 개의 작은 질문으로 쪼갠다.
생각(1): 미국 항목을 따로따로 찾자. 먼저 정부 기구.
행동: usa_ict 입력: 미국 ICT 정부 기구 관찰: [FCC, NTIA]
생각(2): 다음은 주요 법령.
행동: usa_ict 입력: 미국 ICT 주요 법령 관찰: [반도체 과학법]
생각(3): 다음은 기업 진출 사례.
행동: usa_ict 입력: 미국 기업 진출 사례 관찰: [한-미 FTA, MOU]
생각(4): 이제 일본 AI 정책.
행동: japan_ict 입력: 일본 AI 정책 관찰: [경산성 인재 지침]
생각(5): 다 모였다. 정리해서 답하자.
최종 답변: [4개 항목 종합]
usa_ict 세 번, japan_ict 한 번. 총 네 번 검색했다.
누가 시키지도 않았는데, AI가 질문을 쪼개고 순서를 짜서 도구를 골라 가며 풀었다.
이게 에이전트 RAG의 힘이다.
핵심 비교 — 일반 RAG vs 에이전트 RAG
도입부의 질문으로 돌아가 정리하자.
| 구분 | 일반 RAG | 에이전트 RAG |
|---|---|---|
| 검색 횟수 | 1번 (고정) | 필요한 만큼 여러 번 |
| 도구 선택 | 검색기 1개 고정 | AI가 여러 도구 중 고름 |
| 잘 맞는 질문 | 단순 사실 조회 | 비교·복합·여러 단계 질문 |
| 만들기 | 쉬움 | 손이 더 감 (도구 설명·프롬프트) |
| 자주 깨지는 곳 | 검색 품질 | 도구 설명 모호 / 형식 오류 |
한 문장 요약 — 에이전트 RAG는 AI가 생각의 사슬로 상황을 따져 가며, 도구를 스스로 골라 검색을 반복하는 ReAct 사이클로, 한 번 검색으로는 못 푸는 복잡한 질문을 단계별로 푼다.
정리
- ReAct = 생각→행동→관찰을 답 나올 때까지 반복. 탐정처럼 단서를 모은다.
- 생각의 사슬(CoT) = 풀이 과정 먼저 쓰기. ReAct가 매 행동 전 "생각"으로 이를 강제한다.
- 에이전트 RAG = 검색을 여러 번 도는 RAG. 비교·복합 질문도 스스로 쪼개 푼다.
- 도구 설명(description) 과 온도 0 이 흔들리면 AI가 헷갈린다. 이 둘을 또박또박 챙겨라.
한 걸음 더 ▸ (지금 몰라도 됨)
에이전트가 실수하는 가장 흔한 원인 둘은 도구 설명이 모호한 것과 온도가 높은 것이다.
그래서 이 둘만 챙겨도 절반은 간다. 설명을 구체적으로, 온도는 0으로.
검색을 얼마나 반복할지, 도구를 몇 개 둘지 같은 더 깊은 튜닝은 나중에 필요할 때 손대면 된다. 지금은 "AI가 스스로 반복 검색한다"는 큰 줄기만 들고 가면 충분하다.
더 해보기
검증된 외부 자료(Tier 1 공식, 생존 확인 2026-05-21). 책에는 클릭 링크가 없어 여기 모았다.
- 책 공식 실습 노트북(코랩) — ReAct Agent 바로 열기 (사고·행동·관찰 루프 종합 실습)
- 실습 코드 깃허브(Ch07) — langchain-kr/langchain-tutorial
- ReAct 원논문(프린스턴·구글, 2022) — arxiv.org/abs/2210.03629
- ReAct 프로젝트 공식 페이지 — react-lm.github.io
- 랭체인 도구 호출 개념 — concepts/tool_calling
- 랭체인 검색기 개념 — concepts/retrievers (0장 검색기 복습)
최신 동향 (검증 2026-07-09) — 책은 2025년(LangChain 0.3) 기준이다. 아래만 보태 익히면 된다.
create_agent가 현행 표준. 2025-10 랭체인 1.0부터 책의create_react_agent+AgentExecutor조합(그리고 한때 대안이던 LangGraphcreate_react_agent())이 모두 은퇴하고,from langchain.agents import create_agent한 줄이 표준이 됐다. 본문 코드는 이 기준으로 갱신돼 있다. (출처: 랭체인 1.0 릴리스 노트)- 모델·가격은 수시로 바뀐다. 책의
gpt-4o표기는 2025년 기준 예시다. 실제로 쓸 땐 공식 모델 목록을 확인하라: OpenAI 모델 · Anthropic 모델.
연습문제
- 설명.
스스로 검색하는 AI 만들기의 핵심을 처음 듣는 사람에게 한 문장으로 설명하라. - 구분. 두 개념(
일반 RAG,에이전트 RAG)을 실제 예시 하나로 구분하라. - 적용. 내 프로젝트나 학습 노트에서 이 장의 개념을 적용해 작게 개선할 지점을 하나 고르라.
부록 A. 쉬운 용어 사전
| 용어 | 아주 쉬운 뜻 | 이 장에서 나온 위치 |
|---|---|---|
| 일반 RAG | 한 번 검색하고 그 결과로 답하는 기본 RAG 방식. | 부록 B와 본문 예시 |
| 에이전트 RAG | 필요하면 여러 번 검색하고 도구를 쓰며 답을 고치는 RAG 방식. | 부록 B와 본문 예시 |
| ReAct | 생각하고 행동하고 관찰한 뒤 다시 생각하는 과정을 반복하는 패턴. | 부록 B와 본문 예시 |
| 단일 검색 | 검색을 한 번만 수행하고 그 결과에 의존하는 방식. | 부록 B와 본문 예시 |
부록 B. 헷갈리는 개념 비교표
| A | B | 구분 포인트 |
|---|---|---|
| 일반 RAG | 에이전트 RAG | 일반 RAG는 한 번 찾고 답하고, 에이전트 RAG는 필요하면 다시 찾고 고친다. |
| ReAct | 단일 검색 | ReAct는 생각-행동-관찰을 반복하고, 단일 검색은 한 번의 검색에 의존한다. |
부록 C. 더 읽을 자료
- 이 장의
더 해보기섹션 — 이미 모아 둔 공식 문서나 실습 링크가 있으면 여기서 먼저 확인한다. - 같은 책의
0장 한눈에 보기— 용어가 막히면 0장의 용어집과 개념 척추로 돌아간다. - 원본 딥다이브판 같은 장 — 입문판을 읽고 큰 흐름이 잡힌 뒤 세부 논리를 더 깊게 확인한다.
- 이 장의
flashcards.json— 읽은 직후 질문만 보고 답을 떠올리는 회상 연습에 쓴다.
부록 D. 연습문제 풀이
- 설명 예시.
스스로 검색하는 AI 만들기는 RAG에서 자료를 더 잘 찾고, 근거를 더 안전하게 붙이고, 답변 흐름을 더 다루기 쉽게 만드는 방법을 보는 장이다. 중요한 것은 용어를 외우는 것이 아니라, 이 개념이 어떤 입력·부품·결정에 영향을 주는지 말로 풀어 보는 것이다. - 구분 예시. 두 개념(
일반 RAG,에이전트 RAG)의 차이는 이렇게 잡으면 된다. 일반 RAG는 한 번 찾고 답하고, 에이전트 RAG는 필요하면 다시 찾고 고친다. 실제 사례를 볼 때는 목적, 입력, 실패했을 때의 증상을 따로 적어 보면 헷갈리지 않는다. - 적용 예시. 가장 작은 개선부터 고른다. 예를 들어 이름을 더 분명히 하거나, 평가 기준을 한 줄 추가하거나, 직접 알 필요 없는 내부 정보를 감추는 식으로 시작한다. 한 번에 크게 갈아엎는 것보다 작은 변경 하나를 확인하며 진행하는 쪽이 입문 단계에 맞다.
다음 장 예고
다음 장에서는 RAG의 성능 자체를 끌어올리는 또 다른 길을 본다.
지금은 "AI가 스스로 검색을 반복한다"는 7장의 큰 줄기만 머리에 있으면 충분하다.
클릭하거나 Space를 눌러 뒤집기